<script setup lang="ts">
import { type PropType, ref, type VNode } from "vue";

defineOptions({ name: "pending-button" });
const props = defineProps({
  fn: { type: Function, required: true },
  fnArgs: { type: [String, Number, Boolean, Object, Array] as PropType<any> },
  type: { type: String as PropType<"default" | "primary" | "text" | "dashed" | "link" | "ghost"> },
  size: { type: String as PropType<"large" | "middle" | "small"> },
  shape: { type: String as PropType<"default" | "circle" | "round"> },
  icon: { type: Object as PropType<VNode> },
  htmlType: { type: String },
  disabled: { type: Boolean },
  block: { type: Boolean },
  danger: { type: Boolean },
  prevent: { type: Boolean, default: false },
  stop: { type: Boolean, default: false },
});

const pending = ref(false);
const onClick = async (e: PointerEvent) => {
  pending.value = true;
  try {
    if (props.prevent) e.preventDefault();
    if (props.stop) e.stopPropagation();
    if (Array.isArray(props.fnArgs)) {
      await props.fn(...props.fnArgs, e);
    } else {
      await props.fn(props.fnArgs, e);
    }
  } finally {
    pending.value = false;
  }
};
</script>

<template>
  <a-button :type="type" :size="size" :icon="icon" :shape="shape" :html-type="htmlType" :loading="pending" :disabled="disabled" @click="onClick">
    <slot />
  </a-button>
</template>
